import hashlib
from web import models
import json
import time


def object_to_direct(object_):  # 将对象数据转换成字典类型的方法
    return {'id': object_.id,'order_id':object_.order_id,'order_date':object_.order_date,'ship_date':object_.ship_date,'ship_mode':object_.ship_mode,'customer_id':object_.customer_id,'customer':object_.customer_name,'segment':object_.segment,'country':object_.country,'city':object_.city,'state':object_.state,'postal_code':object_.postal_code,'region':object_.region,'product_id':object_.product_id,'category':object_.category,'sub_category':object_.sub_category,'product_name':object_.product_name,'sales':object_.sales,'is_block':object_.is_block}


def Block(data, prev_hash):
    """
    :param data: 传入json化的block数据
    :param prev_hash: 传入前一个区块的hash值
    :return:
    """
    block = {
        "data": data,
        "prev_hash": prev_hash,
        "nonce": 0,
        "time_stamp": time.time()
    }
    return block


"""计算区块的哈希值"""


def hash(block):
    """
    只需传入区块，会自动将区块json化
    :param block: 传入一个区块
    :return:
    """
    message = hashlib.sha256()
    message.update(json.dumps(block).encode('utf-8'))
    print(message.hexdigest())
    return message.hexdigest()


"""生成创世区块，创世区块是第一个区块，无父区块哈希"""


def create_generate_block():
    block = Block("Genesis Block", "")
    powwork = ProofOfWork(block)
    nonce, digest = powwork.mine()
    block["nonce"] = nonce
    models.Block.objects.create(hash=block["prev_hash"], order_id="Genesis Block", customer_id="Genesis Block",
                                product_id="Genesis Block", block=json.dumps(block))


"""添加区块"""


def add_block(nid):
    """
    :param nid:传入需要加入订单 的id
    :return:
    """
    data_list = models.Order.objects.filter(id=nid).first()
    data_list.is_block = -1
    prev_blockinfo = get_last_block()
    prev_block = prev_blockinfo.block
    prev_block = json.loads(prev_block)
    """
        不能直接将对象序列化成json，需要先通过函数将对象转成字典，然后再转成json
        default参数表示一个函数，当前面的参数value无法被序列化时，调用后面的方法进行相应的处理。
        """
    new_block = Block(json.dumps(data_list,default=object_to_direct), hash(prev_block))
    powork = ProofOfWork(new_block)
    nonce, digest = powork.mine()
    new_block["nonce"] = nonce
    models.Block.objects.create(hash=new_block["prev_hash"], order_id=data_list.order_id,
                                customer_id=data_list.customer_id, product_id=data_list.product_id,
                                block=json.dumps(new_block))
    models.Order.objects.filter(id=nid).update(is_block=-1)

"""工作量证明PoW"""


class ProofOfWork:

    def __init__(self, block):
        self.block = block

    def mine(self):
        """
        挖矿函数
        :return:
        """
        i = 0
        prefix = "0000"

        while True:
            nonce = i
            message = hashlib.sha256()
            self.block["nonce"]=nonce
            message.update(json.dumps(self.block).encode('utf-8'))
            digest = message.hexdigest()
            if digest.startswith(prefix):
                print(nonce, digest)
                return nonce, digest
            i += 1


"""获取下一个区块存储的real_hash"""
def getRealHash(id):
    try:
        next_blockinfo = models.Block.objects.filter(id=int(id)+1).first()
        real_hash = next_blockinfo.hash
        return real_hash
    except:
        return "该区块为最后一个区块"

"""计算该区块现在的hash值now_hash"""
def getNowHash(block):
    block = json.loads(block)
    now_hash = hash(block)
    return now_hash

# 获取最后一个区块
def get_last_block():
    last_block = models.Block.objects.all().last()
    return last_block

